package net.wanho.commons.factory;

import java.util.HashMap;
import java.util.Map;

import net.wanho.commons.proxy.TransactionProxy;

/**
 * <工厂类>
 *
 * @author zj
 * @author zcf 简化工厂 通过class类型简单名称获得 该类型的实现类
 * @version [V1.0.0, 2017-4-10]
 * @version [V1.0.1, 2017-4-10]
 */
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.List;

public abstract class BeanFactory {
    private static Map<String,Object> beanMap = new HashMap<>() ;
    private BeanFactory(){}

    static {
        InputStream is = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml") ;
        try{
            //1.dom4j的解析器
            SAXReader saxReader = new SAXReader();
            Document doc = saxReader.read(is);
            List<Element> beanEltList = doc.selectNodes("//beans/bean");
            //IOC 过程： 通过工厂 new Bean 存放在map中
            for (Element beanElt : beanEltList) {
                String id = beanElt.attributeValue("id");
                String clz = beanElt.attributeValue("class");
                // 通过类的完整名称 获得 Class对象
                Class<?> c = Class.forName(clz);
                // 通过反射调用 默认无参构造 new
                Object obj = c.newInstance();
                //存放在map中
                beanMap.put(id,obj) ;
            }
            // DI 过程: 给bean的属性进行赋值
            List<Element> beanEltList2 = doc.selectNodes("//beans/bean");
            //IOC 过程： 通过工厂 new Bean 存放在map中
            for (Element beanElt : beanEltList2) {
                String id = beanElt.attributeValue("id");
                //查找当前bean 标签下 所有 <property 标签
                List<Element> propertyEltList = beanElt.selectNodes("./property");
                //没有属性进行 DI 赋值操作
                if (propertyEltList==null || propertyEltList.isEmpty()){
                    continue;
                }
                Object currObj = beanMap.get(id);
                for (Element propertyElt : propertyEltList) {
                    String name = propertyElt.attributeValue("name");
                    String ref = propertyElt.attributeValue("ref");
                    Object refObj = beanMap.get(ref);
                    //获得当前类的  属性对象
                    Field field = currObj.getClass().getDeclaredField(name);
                    field.setAccessible(true);
                    field.set(currObj,refObj);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static <T> T getBean(Class interfaceCls){
        //根据key 从map中获得
        Object targertObj =  beanMap.get(interfaceCls.getSimpleName());
        //事务代理 只针对 Service层
        if (interfaceCls.getSimpleName().endsWith("Service")){
            return (T) TransactionProxy.createProxy(targertObj);
        }
        //其他层对象 直接返回 不进行代理
        return (T) targertObj;
    }
}
